package cn.sjxy.config.mvcExtend;

import cn.sjxy.baseLib.SjuException;
import cn.sjxy.model.Md_LoginUser;
import cn.sjxy.service.Sv_Login;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 自定义的登录拦截器
 * 这里的拦截器例子是针对前后端分离的场景，无法使用在JSP环境
 * JSP环境下可以通过Session类判断用户是否登录，相对比较简单
 */
@Component
public class CheckLoginInterceptor implements HandlerInterceptor {

   @Autowired
   private RedisTemplate redisTemplate;
   @Autowired
   private Sv_Login sv_login;

   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse
         response, Object handler) throws Exception {
      //如果是options请求，自动返回200
      if (request.getMethod().equals("OPTIONs") ||
            request.getMethod().equals("options")) {
         response.setStatus(200);
         return true;
      }
      //如果不是映射到方法直接通过
      if (!(handler instanceof HandlerMethod))
         return true;
      //获取映射的方法
      HandlerMethod handlerMethod = (HandlerMethod) handler;
      Method method = handlerMethod.getMethod();

      String token = null;
      //如果需要登录,确认请求头中携带了token
      if (method.getDeclaringClass().isAnnotationPresent(NeedAdminLogin.class) ||
            method.isAnnotationPresent(NeedAdminLogin.class) ||
            method.getDeclaringClass().isAnnotationPresent(NeedUserLogin.class) ||
            method.isAnnotationPresent(NeedUserLogin.class)) {

         //从请求头里边获取token
         token = request.getHeader("token");
         System.out.println("=== Token: " + token);
         if (token == null)
            SjuException.loginEx("请先登录");

         //判断Redis中是否存在
         if (redisTemplate.hasKey("UserToken:" + token) == false)
            SjuException.loginEx("请先登录");

         //获取登录用户
         Md_LoginUser user = sv_login.getLoginUser(token);
         
         //确保用户信息不为空
         if (user == null)
            SjuException.loginEx("登录信息已失效，请重新登录");

         //判断用户类型(管理员)
         if (method.getDeclaringClass().isAnnotationPresent(NeedAdminLogin.class) ||
               method.isAnnotationPresent(NeedAdminLogin.class)) {
            if (user.userType.equals(Md_LoginUser.UserType.admin) == false)
               SjuException.loginEx("请先登录");
         }

         //判断用户类型(用户)
         if (method.getDeclaringClass().isAnnotationPresent(NeedUserLogin.class) ||
               method.isAnnotationPresent(NeedUserLogin.class)) {
            if (user.userType.equals(Md_LoginUser.UserType.user) == false)
               SjuException.loginEx("请先登录");
         }

         //将登录用户信息放入request中，供Controller使用
         request.setAttribute("loginUser", user);
      } else {
      }
      return true;
   }

   @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
      HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
   }

   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
      HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
   }

}
